package com.landmesure.communication;

import android.util.Log;

import com.code.CollectData;
import com.code.EntityType;
import com.code.JsonToJavabean;
import com.code.PropertyDefinition;
import com.landmesure.bluetoothchat.view.BluetoothFragment;

import com.landmesure.core.ReadEntity;
import com.landmesure.utils.PropertyBuilder;
import com.util.ByteUtil;

import org.apache.commons.lang3.RandomUtils;
import org.junit.Test;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.content.ContentValues.TAG;


public class ReadBoardEngine {
    private static Map<Integer, Object> fcodeMap ;
    public static boolean isReadMeasureBoard = false;
    private static final int MEASURE_CODE = 2;//判断是否为测量板
    private static final int MEASURE_MCODE = 10;//测量板大类
    private static List<ReadEntity> readEntityList ;
    private static List<Integer> ecodeList ;//保存对象ecode
    private static ArrayList<CollectData> collectDataList ;//对象信源信宿集合
    private static EntityType lastEntityType;

    /**
     * 解码初始化
     */
    public static void init() {
        fcodeMap=new HashMap<>();
        readEntityList = new ArrayList<>();
        ecodeList = new ArrayList<>();
        collectDataList = new ArrayList<>();
    }

    public static EntityType decode(String str) throws CloneNotSupportedException, ParseException {//解析对象
        EntityType entityClone = null;//对象clone
        List<com.code.EntityType> entityTypes = JsonToJavabean.getEntityTypes();
        int mcode = Integer.parseInt(str.substring(32, 34), 16);
        int code = Integer.parseInt(str.substring(36, 38), 16);
        int ecode = Integer.parseInt(str.substring(26, 30), 16);
        //判断是否当前是否读取到测量板
        if (isReadOnMeasureBoard(entityTypes, mcode, code, ecode)) return null;
        for (EntityType entity : entityTypes) {
            if (entity.getMcode() == mcode && entity.getCode() == code) {
                if (oldEntity(mcode, code, ecode)) {
                    entityClone = dealWithOldEntity(str, ecode, entity);
                } else {
                    dealWithNewEntity(str, mcode, code, ecode, entity);
                }
            }
        }
        return entityClone;

    }


    private static void dealWithNewEntity(String str, int mcode, int code, int ecode, EntityType e) {
        CollectData collectData = spiltSourceCodeToCollectData(str, new CollectData());
        if (null != collectData) {
            int fcode = Integer.parseInt(str.substring(40, 44), 16);
            fcodeMap.put(ecode, fcode);//添加父对象编码到map
            queryParameter(e, collectData);
            ReadEntity readEntity = new ReadEntity();
            readEntity.setMcode(mcode);
            readEntity.setCode(code);
            readEntity.setEcode(ecode);
            readEntityList.add(readEntity);
        }

    }

    private static EntityType dealWithOldEntity(String str, int ecode, EntityType entityType) throws CloneNotSupportedException, ParseException {
        lastEntityType = entityType;
        List<EntityType> entityTypes = JsonToJavabean.getEntityTypes();
        EntityType entityClone = null;
        if (!ecodeList.contains(ecode) && ecodeList.size() > 0) {
            for (EntityType et : entityTypes) {
                if (ecodeList.get(ecodeList.size() - 1) == et.getEcode()) {
                    if (et.getEcode() != 65534) {
                        et.setFcode((Integer) fcodeMap.get(et.getEcode()));
                    }
                    entityClone = (EntityType) et.clone();

                }
            }
        }
        ecodeList.add(ecode);
        entityType.setEcode(ecode);//对象编码
        decodeProperty(entityType, str);
        return entityClone;
    }

    public static void readBoardEnd() {
        if (lastEntityType != null) {
            lastEntityType.setFcode((Integer) fcodeMap.get(lastEntityType.getEcode()));
            BluetoothFragment.entityList.add(lastEntityType);//一个板级对象的所有数据
        }
        BluetoothFragment.collectDataMap.put(BluetoothFragment.classKey, (ArrayList) collectDataList.clone());//保存对象信源信宿
        BluetoothFragment.boardMap.put(BluetoothFragment.classKey, (ArrayList) BluetoothFragment.entityList.clone());
        BluetoothFragment.landCommunicationServiceInstance.setData((ArrayList) BluetoothFragment.entityList.clone());

    }

    private static boolean isReadOnMeasureBoard(List<EntityType> entityTypes, int mcode, int code, int ecode) throws CloneNotSupportedException {
        //是否读取测量板
        if (isReadMeasureBoard)
            return false;
        for (EntityType e : entityTypes) {
            if (e.getMcode() == mcode && e.getCode() == code) {
                if (mcode == MEASURE_MCODE && code == MEASURE_CODE) {
                    e.setEcode(ecode);
                    e.setCode(code);
                    e.setMcode(mcode);
                    BluetoothFragment.boardList.add((EntityType) e.clone());
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean oldEntity(int mcode, int code, int ecode) {
        for (ReadEntity readEntity : readEntityList) {
            if ((readEntity.getCode() == code && readEntity.getMcode() == mcode)
                    && readEntity.getEcode() == ecode) {
                return true;
            }
        }
        return false;
    }

    private static void decodeProperty(EntityType entityType, String str) throws ParseException {//参数解码
        String dataStr = str.substring(38, str.length() - 10);
        List<PropertyDefinition> propertyDefinitions = entityType.getPropertyDefinitions();
        Log.i(TAG, "yuan对象名称: " + entityType.getName());
        decodePropertyValue(dataStr, propertyDefinitions);
    }

    private static void decodePropertyValue(String dataStr,
                                            List<PropertyDefinition> propertyDefinitions) throws ParseException {
        int index = 0;
        while (index + 2 < dataStr.length()) {
            int code = Integer.parseInt(dataStr.substring(index, index + 2), 16);
            index = setPropertyValue(index, dataStr, propertyDefinitions, code);
        }
    }

    private static int setPropertyValue(int index, String dataStr, List<PropertyDefinition> propertyDefinitions, int code) throws ParseException {
        Log.i(TAG, "yuan参数编号: " + code);
        Log.i(TAG, "yuan原始数据: " + dataStr);
        PropertyDefinition propertyDefinition = getPropertyByCode(propertyDefinitions, code);
        if (null == propertyDefinition) {
            return 9999;
        }
        //全部设为可编辑
        propertyDefinition.setReadOnly(true);
        int dataLength = propertyDefinition.getDataLength();
        String tempValue = dataStr.substring(index + 2,
                index + 2 + propertyDefinition.getDataLength() * 2);
        String type = propertyDefinition.getVtype();
        //参数值解码
        switch (type) {
            case "integer":
                propertyDefinition.setValue(PropertyBuilder
                        .IntegerBuilder.decode(tempValue, dataLength));
                break;
            case "double":
                propertyDefinition.setValue(PropertyBuilder
                        .FloatBuilder.decode(tempValue, dataLength));
                break;
            case "boolean":
                propertyDefinition.setValue(PropertyBuilder
                        .BooleanBuilder.decode(tempValue, dataLength));
                break;
            case "string":
                propertyDefinition.setValue(PropertyBuilder
                        .AscBuilder.decode(tempValue, dataLength));
                break;
            case "time":
                propertyDefinition.setValue(PropertyBuilder
                        .TimeBuilder.decode(tempValue, dataLength));
                break;
            case "datetime":
                propertyDefinition.setValue(PropertyBuilder
                        .DatetimeBuilder.decode(tempValue, dataLength));
                break;
            default: {
                propertyDefinition.setValue(tempValue);
            }
        }

        index += 2 + propertyDefinition.getDataLength() * 2;
        Log.i(TAG, "yuan: " + propertyDefinition.getName());
        return index;
    }

    private static PropertyDefinition getPropertyByCode(List<PropertyDefinition> propertyDefinitions, int code) {

        for (PropertyDefinition propertyDefinition : propertyDefinitions) {
            if (propertyDefinition.getCode() == code) {
                return propertyDefinition;
            }
        }
        return null;
    }
    private static CollectData spiltSourceCodeToCollectData(String str, CollectData collectData) {
        if(str.length()<40) return null;
        int target=Integer.parseInt(str.substring(6, 10),16);
        collectData.setTargetStation(target>>6);
        collectData.setTargetGroup(target&0x003F);
        int source=Integer.parseInt(str.substring(10, 14),16);
        collectData.setSourceStation(source>>6);
        collectData.setSourceGroup(source&0x003F);
        int router=Integer.parseInt(str.substring(14, 18),16);
        collectData.setRouter(router>>6);
        collectData.setRouterGroup(router&0x003F);
        int index=Integer.parseInt(str.substring(18, 20),16);
        collectData.setIndex(index);
        collectData.setData(str.substring(20, 20+Integer.parseInt(str.substring(4, 6),16)*2));
        String pcode=str.substring(24, 26);//工程号
        collectData.setPcode(Integer.valueOf(pcode));
        int ecode=Integer.parseInt(str.substring(26, 30),16);//对象编号
        collectData.setEcode(ecode);
        collectDataList.add(collectData);
        return collectData;
    }

    /**
     *
     *查询参数
     */
    private static void queryParameter(EntityType e, CollectData collectData){
        List<PropertyDefinition> propertyDefinitions=e.getPropertyDefinitions();
        int code;
        for (int j = 0; j <propertyDefinitions.size()/5+1; j++) {
            StringBuilder sbcode=new StringBuilder();
            sbcode.append("02");//命令类型
            sbcode.append(collectData.getPcode());
            sbcode.append(String.format("%04X",collectData.getEcode()));
            sbcode.append("0102");//大小类编码
            int k=j*5;
            int l=0;
            for (int i = 0; i <5 ; i++) {
                if(k+i>=propertyDefinitions.size()){l=k+i; break;}//添加查询对象的方法（参数查完）
                code= propertyDefinitions.get(k+i).getCode();//得到对象的参数编码
                sbcode.append(String.format("%02X",code));
            }
            StringBuilder scode=new StringBuilder();
            scode.append("EB95");
            scode.append(String.format("%02X",sbcode.length()/2));
            //转化
            scode.append(String.format("%04X",(collectData.getSourceStation()<<6)+collectData.getSourceGroup()));
            scode.append(String.format("%04X",(collectData.getTargetStation()<<6)+collectData.getTargetGroup()));
            scode.append("0000");
            scode.append("0000");
            scode.append(sbcode);
            scode.append("00");
            scode.append(String.format("%04X", RandomUtils.nextInt(1, 65533)));//"0000"
            scode.append(String.format("%04X", ByteUtil.buildCrc16(scode.toString())));
            SendMessageThread.addTask(scode.toString());
            if(l>=propertyDefinitions.size()){
                queryObject(collectData);//添加查询对象的方法（参数查完）
            }

        }
    }
    /*
    查询对象
     */
    private static void queryObject(CollectData collectData){
        StringBuilder sbcode=new StringBuilder();
        sbcode.append("0A");//命令类型
        sbcode.append(collectData.getPcode());
        sbcode.append(String.format("%04X",collectData.getEcode()));
        sbcode.append("0102");//大小类编码
        StringBuilder scode=new StringBuilder();
        scode.append("EB95");
        scode.append(String.format("%02X",sbcode.length()/2));
        scode.append(String.format("%04X",(collectData.getSourceStation()<<6)+collectData.getSourceGroup()));
        scode.append(String.format("%04X",(collectData.getTargetStation()<<6)+collectData.getTargetGroup()));
        scode.append("0000");
        scode.append("0000");
        scode.append(sbcode);
        scode.append("00");
        scode.append(String.format("%04X", RandomUtils.nextInt(1, 65533)));//"0000"
        scode.append(String.format("%04X", ByteUtil.buildCrc16(scode.toString())));
        SendMessageThread.addTask(scode.toString());
    }
    public static void main(String[] args) {
        StringBuilder sbcode=new StringBuilder();
        sbcode.append("0A");//命令类型
        sbcode.append("05");
        sbcode.append("0BC4");
        StringBuilder scode=new StringBuilder();
        scode.append("EB95");
        scode.append(String.format("%02X",sbcode.length()/2));
        scode.append("0341");
        scode.append("0041");
        scode.append("0000");
        scode.append("0000");
        scode.append(sbcode);
        scode.append("00");
        scode.append(String.format("%04X", RandomUtils.nextInt(1, 65533)));//"0000"
        scode.append(String.format("%04X", ByteUtil.buildCrc16(scode.toString())));
        System.out.println(scode);

    }
    @Test
    public void test(){
        System.out.println(String.format("%04X",(20<<6)+1));
        System.out.println(String.format("%04X",Integer.parseInt(Integer.toHexString(66),16)));
    }

}
